package services

import (
	"go-ddd-ecommerce/internal/application/dto"
	"go-ddd-ecommerce/internal/application/event_handlers"
	"go-ddd-ecommerce/internal/domain/events"
	"go-ddd-ecommerce/internal/domain/order"
	"go-ddd-ecommerce/internal/domain/product"
	purchaseService "go-ddd-ecommerce/internal/domain/services"
	"go-ddd-ecommerce/internal/domain/user"

	"gorm.io/gorm"
)

type OrderAppService struct {
	userRepo        user.Repository                  // 用户仓储
	productRepo     product.Repository               // 商品仓储
	orderRepo       order.Repository                 // 订单仓储
	purchaseService *purchaseService.PurchaseService // 购买服务
	eventPublisher  *events.DomainEventPublisher     // 注入事件发布器
	db              *gorm.DB
}

func NewOrderAppService(
	userRepo user.Repository,
	productRepo product.Repository,
	orderRepo order.Repository,
	purchaseService *purchaseService.PurchaseService,
	eventPublisher *events.DomainEventPublisher, // 注入事件发布器
	db *gorm.DB,
) *OrderAppService {
	service := &OrderAppService{
		userRepo:        userRepo,
		productRepo:     productRepo,
		orderRepo:       orderRepo,
		purchaseService: purchaseService,
		eventPublisher:  eventPublisher,
		db:              db,
	}

	// 注册事件处理器
	service.registerEventHandlers()
	return service
}

// 注册事件处理器
func (s *OrderAppService) registerEventHandlers() {
	// 注册邮件通知处理器
	emailHandler := event_handlers.NewEmailNotificationHandler()
	s.eventPublisher.Subscribe("order.created", emailHandler)
	s.eventPublisher.Subscribe("user.balance_update", emailHandler)

	// 注册库存预警处理器
	inventoryHandler := event_handlers.NewInventoryAlertHandler(10) // 库存阈值设为10
	s.eventPublisher.Subscribe("product.stock_update", inventoryHandler)

	// 注册积分计算处理器
	pointsHandler := event_handlers.NewPointsCalculationHandler()
	s.eventPublisher.Subscribe("order.created", pointsHandler)
}

// 购买商品(修改成支持事件发布)
func (s *OrderAppService) Purchase(cmd dto.CreateOrderDTO) (dto.OrderDataDTO, error) {
	// 1.获取用户的聚合根
	u, err := s.userRepo.FindByID(cmd.UserID)
	if err != nil {
		return dto.OrderDataDTO{}, err
	}

	// 2.获取商品信息
	p, err := s.productRepo.FindByID(cmd.ProductID)
	if err != nil {
		return dto.OrderDataDTO{}, err
	}

	// 3.直接调用购买的领域服务,因为购买的逻辑已经实现在了领域服务哪里了
	o, err := s.purchaseService.Purchase(u, p, cmd.Quantity)
	if err != nil {
		return dto.OrderDataDTO{}, err
	}
	// 开启手动事务
	tx := s.db.Begin()
	if tx.Error != nil {
		return dto.OrderDataDTO{}, tx.Error
	}

	// 使用defer确保事务被正确处理
	defer func() {
		if r := recover(); r != nil {
			tx.Rollback()
		}
	}()

	// 保存聚合根状态
	if err := s.userRepo.Update(u); err != nil {
		tx.Rollback()
		return dto.OrderDataDTO{}, err
	}
	if err := s.productRepo.Update(p); err != nil {
		tx.Rollback()
		return dto.OrderDataDTO{}, err
	}
	if err := s.orderRepo.Save(o); err != nil {
		tx.Rollback()
		return dto.OrderDataDTO{}, err
	}
	// 提交事务
	if err := tx.Commit().Error; err != nil {
		return dto.OrderDataDTO{}, err
	}
	// 发布领域事件（在事务提交后发布，确保数据一致性）
	s.eventPublisher.PublishEvents(u, p, o)
	return dto.OrderDataDTO{
		ID:          o.ID,
		UserID:      o.UserID,
		ProductID:   o.ProductID,
		Quantity:    o.Quantity,
		TotalAmount: o.TotalAmount,
		Status:      o.Status,
		CreatedAt:   o.CreatedAt.Format("2006-01-02 15:04:05"),
	}, nil
}

// 获取用户全部订单
func (s *OrderAppService) GetUserOrders(cmd dto.GetOrderByUserIDDTO) ([]dto.OrderDataDTO, error) {
	orders, err := s.orderRepo.FindByUserID(cmd.UserID)
	if err != nil {
		return nil, err
	}
	var orderDTOList []dto.OrderDataDTO
	for _, order := range orders {
		orderDTOList = append(orderDTOList, dto.OrderDataDTO{
			ID:          order.ID,
			UserID:      order.UserID,
			ProductID:   order.ProductID,
			Quantity:    order.Quantity,
			TotalAmount: order.TotalAmount,
			Status:      order.Status,
			CreatedAt:   order.CreatedAt.Format("2006-01-02 15:04:05"),
		})
	}
	return orderDTOList, nil
}
